package cn.net.dpi.core.exception;

import cn.net.dpi.core.api.vo.Response;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;


@RestControllerAdvice
public class GlobalExceptionHandler {
    private final static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Response<Object> validateExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldError().getField() + ":" +
                e.getBindingResult().getFieldError().getDefaultMessage();
        logger.error("[code:{}], [message:{}], [data:{}]", ApiError.INVALID_PARAM.getCode(),
                ApiError.INVALID_PARAM.getMessage(), message);
        return Response.error(ApiError.INVALID_PARAM.getCode(), message, null);
    }

    @ExceptionHandler(value = Exception.class)
    public Response<Object> defaultExceptionHandler(HttpServletRequest request, Exception e) throws IOException {

        HashMap <String, Object> jsonMap = new HashMap<>(4);
        jsonMap.put("uri", request.getRequestURI());
        jsonMap.put("params", request.getParameterMap());

        ObjectMapper mapper = new ObjectMapper();
        StringBuilder stackMsg = new StringBuilder();
        stackMsg.append(String.format("错误请求：{%s}\n", mapper.writeValueAsString(jsonMap)));
        stackMsg.append(String.format("错误信息：{%s}\n", e));
        for (StackTraceElement s:e.getStackTrace()) {
            stackMsg.append(s.toString());
            stackMsg.append("\n");
        }

        logger.error("[code:{}], [message:{}], [data:{}]", ApiError.ERROR.getCode(), e.getMessage(), stackMsg);
        return Response.error(ApiError.ERROR.getCode(), ApiError.ERROR.getMessage(), null);
    }

    @ExceptionHandler(value = BaseException.class)
    public Response<Object> baseExceptionHandler(HttpServletRequest request, BaseException e) throws IOException {

        HashMap <String, Object> jsonMap = new HashMap<>(4);
        jsonMap.put("uri", request.getRequestURI());
        jsonMap.put("params", request.getParameterMap());

        ObjectMapper mapper = new ObjectMapper();
        StringBuilder stackMsg = new StringBuilder();
        stackMsg.append(String.format("错误请求：{%s}\n", mapper.writeValueAsString(jsonMap)));
        stackMsg.append(String.format("错误信息：{%s}\n", e));
        for (StackTraceElement s:e.getStackTrace()) {
            stackMsg.append(s.toString());
            stackMsg.append("\n");
        }

        logger.error("[code:{}], [message:{}], [data:{}]", e.getCode(), e.getMessage(), stackMsg);
        return Response.error(e.getCode(), e.getMsg(), null);
    }

    @ExceptionHandler(value = FatalException.class)
    public Response<Object> fatalExceptionHandler(HttpServletRequest request, FatalException e) throws IOException {

        HashMap <String, Object> jsonMap = new HashMap<>(4);
        jsonMap.put("uri", request.getRequestURI());
        jsonMap.put("params", request.getParameterMap());

        ObjectMapper mapper = new ObjectMapper();
        StringBuilder stackMsg = new StringBuilder();
        stackMsg.append(String.format("错误请求：{%s}\n", mapper.writeValueAsString(jsonMap)));
        stackMsg.append(String.format("错误信息：{%s}\n", e));
        for (StackTraceElement s:e.getStackTrace()) {
            stackMsg.append(s.toString());
            stackMsg.append("\n");
        }

        logger.error("[code:{}], [message:{}], [data:{}]", e.getCode(), e.getMessage(), stackMsg);
        return Response.error(e.getCode(), e.getMsg(), null);
    }
}

